package com.zipking.cloud.springbootmybatis.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zipking.cloud.springbootmybatis.persistance.entity.MsgLog;
import com.zipking.cloud.springbootmybatis.persistance.mapper.MsgLogMapper;
import com.zipking.cloud.springbootmybatis.service.impl.ThredQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Slf4j
@Service
public class MultiThreadQueryUtil<T> {
    @Autowired
    private MsgLogMapper msgLogMapper;
    /**
     * 获取多线程结果并进行结果合并
     * @return
     */
    public List<List<T>> getMultiCombineResult() {
        //开始时间
        long start = System.currentTimeMillis();
        //返回结果
        List<List<T>> result = new ArrayList<>();
        //查询数据库总数量
        LambdaQueryWrapper<MsgLog> queryWrapper = new LambdaQueryWrapper<MsgLog>();
        queryWrapper.eq(MsgLog::getRoutingKey, "XX");
        int count = msgLogMapper.selectCount(queryWrapper);
        log.info("总条数:{}", count);
//        Map<String,String> splitMap = ExcelLocalUtils.getSplitMap(count,5);
        //假定总数据4条
        int num = 50000;

        /******计算需要查询的次数******/
        int times = count / num;
        if (count % num != 0) {
            times = times + 1;
        }
        int offset = 0;
        List<Callable<List<T>>> tasks = new ArrayList<>();
        for (int i = 1; i <= times; i++) {
            //不同的线程用户处理不同分段的数据量，这样就达到了平均分摊查询数据的压力
            //这里让每个线程每次查询一条数据
            int startNum =i-1;//对应的数据要和i挂钩 ，否则数据不变
            int endNum =1;
            Callable<List<T>> qfe = new ThredQueryExt(offset, num);
            tasks.add(qfe);
            offset = offset + num;
        }
        try{
            //定义固定长度的线程池  防止线程过多，5就够用了
//            ExecutorService executorService = Executors.newFixedThreadPool(5);
            //4条数据，分成4个线程来查询
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            //Future用于获取结果
            List<Future<List<T>>> futures=executorService.invokeAll(tasks);
            //处理线程返回结果
            if(futures!=null&&futures.size() > 0){
                for (Future<List<T>> future:futures){
                    result.addAll((Collection<? extends List<T>>) future.get());
                }
            }
            //关闭线程池，一定不能忘记
            executorService.shutdown();
        }catch (Exception e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("线程查询数据用时:"+(end-start)+"ms");
        return result;
    }

}
